/***************************************************************************
 *   Copyright (C) 2010 by Lasse Liehu                                     *
 *   lliehu@kolumbus.fi                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "notifiersettings.h"

#include <cassert>
#include <QFont>
#include <QSettings>
#include <QCoreApplication>

#include "googlelogindata.h"

#ifdef Q_WS_WIN
#include "integration/win_functions.h"
#endif

//BEGIN NotifierSettingsPrivate
class NotifierSettingsPrivate
{
    public:
        GoogleLoginData loginData;
        int checkingInterval;
        QFont unreadCountDisplayFont;
        bool isUnreadCountShownInWindow;
        NewUnreadItemsNotificationTime notificationTime;
        bool isAutostartEnabled;
};
//END NotifierSettingsPrivate

NotifierSettings::NotifierSettings(bool readSettingsAtConstruction)
    : d(new NotifierSettingsPrivate)
{
    if (readSettingsAtConstruction) readSettings();
    else setToDefaults();
}

NotifierSettings::~NotifierSettings()
{
    delete d;
}

GoogleLoginData& NotifierSettings::loginData()
{
    return d->loginData;
}

const GoogleLoginData& NotifierSettings::loginData() const
{
    return d->loginData;
}

int NotifierSettings::checkingInterval() const
{
    return d->checkingInterval;
}

QFont NotifierSettings::unreadCountDisplayFont() const
{
    return d->unreadCountDisplayFont;
}

bool NotifierSettings::isUnreadCountShownInWindow() const
{
    return d->isUnreadCountShownInWindow;
}

NewUnreadItemsNotificationTime NotifierSettings::notificationTime() const
{
    return d->notificationTime;
}

bool NotifierSettings::isAutostartEnabled() const
{
    return d->isAutostartEnabled;
}

int NotifierSettings::defCheckingInterval() const
{
    return 30;
}

QFont NotifierSettings::defUnreadCountDisplayFont() const
{
    return QFont();
}

bool NotifierSettings::defIsUnreadCountShownInWindow() const
{
    return false;
}

NewUnreadItemsNotificationTime NotifierSettings::defNotificationTime() const
{
    return NUINT_Smart;
}

bool NotifierSettings::defIsAutostartEnabled() const
{
#ifdef Q_WS_WIN
    return true;
#else
    return false;
#endif
}

void NotifierSettings::setCheckingInterval(int interval)
{
    if (interval > 0)
    {
        bool changed = d->checkingInterval != interval;
        d->checkingInterval = interval;
        if (changed) emit checkingIntervalChanged();
    }
}

void NotifierSettings::setUnreadCountDisplayFont(const QFont& font)
{
    bool changed = d->unreadCountDisplayFont != font;
    d->unreadCountDisplayFont = font;
    if (changed) emit unreadCountDisplayFontChanged();
}

void NotifierSettings::setShowUnreadCountInWindow(bool val)
{
    bool changed = d->isUnreadCountShownInWindow != val;
    d->isUnreadCountShownInWindow = val;
    if (changed) emit isUnreadCountShownInWindowChanged();
}

void NotifierSettings::setNotificationTime(NewUnreadItemsNotificationTime newVal)
{
    bool changed = d->notificationTime != newVal;
    d->notificationTime = newVal;
    if (changed) emit notificationTimeChanged();
}

void NotifierSettings::setAutostartEnabled(bool newVal)
{
    bool changed = d->isAutostartEnabled != newVal;
    d->isAutostartEnabled = newVal;
    if (changed) emit isAutostartEnabledChanged();
}

// in this function settingsChanged() may be emitted loads of times
void NotifierSettings::setToDefaults()
{
    d->loginData.setPassword("");
    d->loginData.setEmail("");
    d->loginData.setSid("");
    d->loginData.setSavePassword(false);

    setCheckingInterval(defCheckingInterval() );
    setUnreadCountDisplayFont(defUnreadCountDisplayFont() );
    setShowUnreadCountInWindow(defIsUnreadCountShownInWindow() );
    setNotificationTime(defNotificationTime() );
    setAutostartEnabled(defIsAutostartEnabled() );
}

/**
  * Reads settings from settings storage on disk.
  * @attention This function @b must set each setting to a valid value, even
  * if it couldn't be read. That is because a class may be initialized with
  * values set only from this function and thus some values could end up
  * uninitialized.
  */
void NotifierSettings::readSettings()
{
    QSettings settings;
    d->loginData.setEmail(settings.value("acc_email", QString("")).toString() );
    QString password = settings.value("acc_password", QString("")).toString();
    // making the password readable again
    for (int i = 0; i < password.length(); ++i)
    {
        password[i] = QChar(password[i].unicode()-11);
    }
    d->loginData.setPassword(password);
    d->loginData.setSavePassword(settings.value("save_acc_password", false).toBool() );

    d->checkingInterval = settings.value("checking_interval",
        defCheckingInterval()).toInt();
    d->unreadCountDisplayFont = QFont(settings.value("systray_countfont",
        defUnreadCountDisplayFont() ).toString() );
    d->isUnreadCountShownInWindow = settings.value("is_unreadcountwin_open",
        defIsUnreadCountShownInWindow() ).toBool();

    int notificationTime = settings.value("newunreaditems_notificationtime",
        defNotificationTime() ).toInt();
    switch (notificationTime)
    {
        case NUINT_Always:
            d->notificationTime = NUINT_Always;
            break;
        case NUINT_Smart:
            d->notificationTime = NUINT_Smart;
            break;
        case NUINT_Never:
            d->notificationTime = NUINT_Never;
            break;
        default:
            d->notificationTime = defNotificationTime();
            assert(false);
    }

#ifdef Q_WS_WIN
    bool askedToSetAutostartOn = settings.value("set_autostart_on", false).toBool();
    settings.remove("set_autostart_on");

    if (askedToSetAutostartOn)
    {
        notifier::setAutostartForApp(
            QCoreApplication::applicationName(),
            QCoreApplication::applicationFilePath() );
    }
    d->isAutostartEnabled = notifier::hasAutostartForApp(
        QCoreApplication::applicationName() );
#else
    d->isAutostartEnabled = false;
#endif

    emit settingsRead();
    // TODO do some boring optimization so that all of these signals aren't
    // emitted if they didn't _really_ change
    emit checkingIntervalChanged();
    emit unreadCountDisplayFontChanged();
    emit isUnreadCountShownInWindowChanged();
    emit notificationTimeChanged();
    emit isAutostartEnabledChanged();
}

void NotifierSettings::writeSettings()
{
    QSettings settings;
    settings.setValue("acc_email", d->loginData.email() );
    QString password = d->loginData.password(GoogleLoginData::Saved);
    // making the saved password just a bit more secure
    for (int i = 0; i < password.length(); ++i)
    {
        password[i] = QChar(password[i].unicode()+11);
    }
    settings.setValue("acc_password", password);
    settings.setValue("save_acc_password", d->loginData.isPasswordSaved() );
    settings.setValue("checking_interval", d->checkingInterval);
    settings.setValue("systray_countfont", d->unreadCountDisplayFont);
    settings.setValue("is_unreadcountwin_open", d->isUnreadCountShownInWindow);
    settings.setValue("newunreaditems_notificationtime", d->notificationTime);

#ifdef Q_WS_WIN
    if (d->isAutostartEnabled)
    {
        notifier::setAutostartForApp(
            QCoreApplication::applicationName(),
            QCoreApplication::applicationFilePath() );
    }
    else
    {
        notifier::unsetAutostartForApp(
            QCoreApplication::applicationName() );
    }
#endif
}
